Skip to content

feat(admin): Policy listing + Diagnostics + Settings + custom metrics (Phase A3)#13

Merged
jlc488 merged 1 commit into
mainfrom
feat/policies-diagnostics-settings-metrics
May 27, 2026
Merged

feat(admin): Policy listing + Diagnostics + Settings + custom metrics (Phase A3)#13
jlc488 merged 1 commit into
mainfrom
feat/policies-diagnostics-settings-metrics

Conversation

@jlc488

@jlc488 jlc488 commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Phase A3 — last big backend gap before the admin-ui pages can drive every feature the kit exposes. Adds 4 new controllers + a metrics autoconfig.

Stacked on #11, #12.

admin-api (4 new controllers)

PolicyAdminController/admin/api/v1/policies

Verb Path Action
GET / list registered Policy bean names
POST /{name}/test dry-run evaluate with a PolicyContextALLOW / DENY / NOT_APPLICABLE

DefaultPolicyEvaluator gains registeredNames() for the listing path.

SettingsAdminController/admin/api/v1/settings

Verb Path Action
GET / read-only view of devslab.kit.* properties (jwt.secret masked)

Implemented against Environment rather than DevslabKitProperties to keep the dependency graph acyclicadmin-api must not depend on autoconfigure, which already depends on admin-api. Mutating settings at runtime needs RefreshScope / external config; out of scope.

DiagnosticsController/admin/api/v1/diagnostics

Verb Path Action
POST /login-test run LoginCommand through LocalLoginService; returns success + reason. Note: this increments the real lockout counter — admins should be careful using it as a probe.
POST /permission-check {userId, permissionCode}{allowed, userPermissionCodes}
GET /menu-visibility?userId= filter the user's tenant's menu tree by the permission codes that user actually has (uses MenuTreeBuilder + manual filter rather than PermissionBasedMenuFilter so it doesn't hijack the current SecurityContext)

(TenantAdminController from PR #12 sits alongside these.)

autoconfigure: MetricsAutoConfiguration (planning §13)

Listens to identity events and increments Micrometer counters with tenant + reason tags:

devslab.identity.login.success {tenant}
devslab.identity.login.failure {tenant, reason}
  • Activated by @ConditionalOnClass(MeterRegistry.class)
  • Consumer apps that ship spring-boot-starter-actuator get the counters at /actuator/metrics/{name}
  • Apps that don't pull Micrometer skip the listener entirely
  • Registered in AutoConfiguration.imports

micrometer-core added as compileOnly to autoconfigure — no forced dep on apps that don't want metrics.

Verified

./gradlew :devslab-kit-sample-app:test  → BUILD SUCCESSFUL in 1m 8s
  • All 4 new controllers wire
  • MetricsAutoConfiguration activates (actuator is on sample-app's classpath)
  • All previous beans, login flow, tenant CRUD still green

Deferred

  • A4 (Swagger UI) — still waiting on a Spring Boot 4 compatible springdoc-openapi release (current 2.7.0 calls org.springframework.data.util.TypeInformation which Spring Data 4 moved)
  • Permission denied + tenant resolve failure + menu load duration metrics — needs AOP or interceptor; deferred until a clear consumer ask
  • Runtime settings write — RefreshScope / Spring Cloud Config required, separate starter

Phase A3 — last big backend gap before admin-ui pages can drive every
feature the kit exposes.

## admin-api: 4 new controllers

PolicyAdminController (/admin/api/v1/policies)
- GET /                  list registered Policy bean names
- POST /{name}/test      dry-run evaluate with a PolicyContext, returns
                         ALLOW / DENY / NOT_APPLICABLE
- DefaultPolicyEvaluator gains registeredNames() for the listing path.

SettingsAdminController (/admin/api/v1/settings)
- GET /                  read-only view of devslab.kit.* properties
- Sensitive fields (jwt.secret) masked with "***".
- Implemented against Environment rather than DevslabKitProperties to
  keep the dependency graph acyclic (admin-api must not depend on
  autoconfigure, which already depends on admin-api).
- Mutating settings at runtime needs RefreshScope / external config;
  deliberately out of scope.

DiagnosticsController (/admin/api/v1/diagnostics)
- POST /login-test       run LoginCommand through LocalLoginService;
                         returns success + reason; note this does
                         increment the lockout counter, so admins
                         should be careful using it as a probe.
- POST /permission-check {userId, permissionCode} -> {allowed, userPermissionCodes}
- GET  /menu-visibility?userId=  filter the user's tenant's menu tree
                         by the permission codes that user actually has
                         (uses MenuTreeBuilder + manual filter rather
                         than PermissionBasedMenuFilter so it doesn't
                         hijack the current SecurityContext)

TenantAdminController (already shipped in PR #12) sits alongside these.

## autoconfigure: MetricsAutoConfiguration

Per planning §13. Listens to identity events and increments
Micrometer counters with tenant + reason tags:

  devslab.identity.login.success {tenant}
  devslab.identity.login.failure {tenant, reason}

Activated by @ConditionalOnClass(MeterRegistry.class). Consumer apps
that ship spring-boot-starter-actuator get the counters at
/actuator/metrics/{name}; apps that don't pull Micrometer skip the
listener entirely.

Registered in AutoConfiguration.imports.

micrometer-core added as compileOnly to autoconfigure so we don't
force the dep on apps that don't want metrics.

Verified: ./gradlew :devslab-kit-sample-app:test  -> BUILD SUCCESSFUL in 1m 8s
- All 4 new controllers wire
- MetricsAutoConfiguration activates (actuator is on sample-app's classpath)
- All previous beans, login flow, tenant CRUD still green
@jlc488
jlc488 merged commit 823a6a8 into main May 27, 2026
1 check passed
@jlc488
jlc488 deleted the feat/policies-diagnostics-settings-metrics branch May 30, 2026 06:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant